package cn.msqweb.config;




import cn.msqweb.constant.AuthConstants;
import cn.msqweb.constant.BusinessEnum;
import cn.msqweb.impl.UserDetailsServiceImpl;
import cn.msqweb.model.LoginResult;
import cn.msqweb.model.Result;
import cn.msqweb.model.SecurityUser;
import cn.msqweb.util.JsonUtils;
import cn.msqweb.util.JwtJson;
import cn.msqweb.util.ResponseUtils;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import java.time.Duration;
import java.util.UUID;

/**
 * Security安全框架的配置类
 */
@Configuration
@Slf4j
public class AuthSecurityConfig{

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception{
        return httpSecurity
                .csrf(csrf -> csrf.disable())
                .cors(cors -> cors.disable())
                .sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .formLogin(formLogin -> {
                    formLogin
                            .loginProcessingUrl(AuthConstants.LOGIN_URL)
                            .successHandler(authenticationSuccessHandler())
                            .failureHandler(authenticationFailureHandler());
                })
                .logout(logout -> {
                    logout
                            .logoutUrl(AuthConstants.LOGOUT_URL)
                            .logoutSuccessHandler(logoutSuccessHandler());
                })
                .authorizeHttpRequests(auth -> {
                    auth.anyRequest().authenticated();
                })
                .build();
    }

    /**
     * 登录成功处理器
     * 1.生成token
     * 2.并将token存放到redis缓存中
     * 3.将token信息响应给前端
     * @return
     */
    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
        return (request, response, authentication) -> {


            // 从security容器中获取当前登录的用户身份信息    --> redis.value
            String SecurityUserJsonSter = JSON.toJSONString(authentication.getPrincipal());
            System.out.println("SecurityUserJsonSter = " + SecurityUserJsonSter);
            String token = JwtJson.createJWT(SecurityUserJsonSter);
            stringRedisTemplate.opsForValue().set(AuthConstants.LOGIN_TOKEN_PREFIX + token, "", Duration.ofSeconds(AuthConstants.TOKEN_TIME));

            //把token给到前端加token有效时长给前端
            LoginResult loginResult = new LoginResult(token, AuthConstants.TOKEN_TIME);
            Result<LoginResult> success = Result.success(loginResult);
            String s = new ObjectMapper().writeValueAsString(success);
            ResponseUtils.weter(response,s);
        };
    }
    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler(){
        return (request, response, exception) -> {

            Result success = new Result();
            success.setCode(BusinessEnum.UN_AUTHORIZATION.getCode());
            success.setMsg("登录失败");

            //把结果给前端
            String s = new ObjectMapper().writeValueAsString(success);
            ResponseUtils.weter(response,s);

        };
    }
    @Bean
    public LogoutSuccessHandler logoutSuccessHandler(){
        return (request, response, authentication) -> {
            String authorization = request.getHeader(AuthConstants.AUTHORIZATION);
            String token = authorization.replaceFirst(AuthConstants.BEARER, "");

            stringRedisTemplate.delete(AuthConstants.LOGIN_TOKEN_PREFIX+token);
            Result<Object> success = Result.success(null);
            String s = JsonUtils.objToJson(success);
            ResponseUtils.weter(response,s);
        };
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
